import { ActionConfiguration, AppConfiguration, BelongsToConfiguration, ColumnConfiguration, DatasourceConfiguration, ElementConfiguration, HabtmConfiguration, HasManyConfiguration, HasOneConfiguration, HomeConfiguration, LayoutConfiguration, MicroConfiguration, SeedConfiguration, StatConfiguration } from "@/views/dev-types";
import { isObject, isArray } from 'lodash-es';

export function clear(app: AppConfiguration) {
  if(!app.version) delete app.version
  if(!app.logo) delete app.logo
  if(!app.copyright) delete app.copyright
  

  // groups?: Record<string, GroupConfiguration> // 键为分组名称
  if(!app.micros || Object.keys(app.micros).length === 0) {
    delete app.micros
  } else {
    clearMicros(app.micros)
  }

  if(!app.root) delete app.root
  if(!app.rootLayout || Object.keys(app.rootLayout).length === 0) {
    delete app.rootLayout
  } else {
    clearLayout(app.rootLayout)
  }
  if(!app.rootProps || Object.keys(app.rootProps).length === 0) {
    delete app.rootProps
  } else {
    clearComponentProps(app.rootProps)
  }

  if(!app.login) delete app.login
  if(!app.loginLayout || Object.keys(app.loginLayout).length === 0) {
    delete app.loginLayout
  } else {
    clearLayout(app.loginLayout)
  }
  if(!app.loginProps || Object.keys(app.loginProps).length === 0) {
    delete app.loginProps
  } else {
    clearComponentProps(app.loginProps)
  }

  if(!app.home) delete app.home
  if(!app.homeLayout || Object.keys(app.homeLayout).length === 0) {
    delete app.homeLayout
  } else {
    clearLayout(app.homeLayout)
  }
  if(!app.homeProps || Object.keys(app.homeProps).length === 0) {
    delete app.homeProps
  } else {
    clearComponentProps(app.homeProps)
  }

  if(!app.error) delete app.error
  if(!app.errorLayout || Object.keys(app.errorLayout).length === 0) {
    delete app.errorLayout
  } else {
    clearLayout(app.errorLayout)
  }
  if(!app.errorProps || Object.keys(app.errorProps).length === 0) {
    delete app.errorProps
  } else {
    clearComponentProps(app.errorProps)
  }

  if(!app.redirect) delete app.redirect
  if(!app.redirectLayout || Object.keys(app.redirectLayout).length === 0) {
    delete app.redirectLayout
  } else {
    clearLayout(app.redirectLayout)
  }
  if(!app.redirectProps || Object.keys(app.redirectProps).length === 0) {
    delete app.redirectProps
  } else {
    clearComponentProps(app.redirectProps)
  }

  clearMicro(app)
}

function clearLayout(layout: LayoutConfiguration) {
  if(!layout.type) delete layout.type
  if(!layout.component) delete layout.component
  if(!layout.componentProps || Object.keys(layout.componentProps).length === 0) {
    delete layout.componentProps
  } else {
    clearComponentProps(layout.componentProps)
  }
  if(!layout.style || Object.keys(layout.style).length === 0) delete layout.style
  if(!layout.cls || layout.cls.length === 0) delete layout.type
  if(!layout.content) delete layout.content
  if(!layout.children || layout.children.length === 0) {
    delete layout.children
  } else {
    for(const child of layout.children) clearLayout(child)
  }
}

function clearComponentProps(componentProps: Record<string, any>) {
  for(const key in componentProps) {
    const value = componentProps[key]
    if(isObject(value)) {
      if(Object.keys(value).length === 0) {
        delete componentProps[key]
      } else {
        clearComponentProps(value)
      }
    } else if(isArray(value)) {
      if(value.length === 0) {
        delete componentProps[key]
      } else {
        clearComponentProps(value)
      }
    } else if(!value) {
      delete componentProps[key]
    }
  }
}

function clearHomes(homes: Record<string, HomeConfiguration>) {
  for(const homeName in homes) {
    const home = homes[homeName]
    if(Object.keys(home).length === 0) {
      delete homes[homeName]
    } else {
      clearHome(home)
      if(Object.keys(home).length === 0) delete homes[homeName]
    }
  }
}

function clearHome(home: HomeConfiguration) {
  if(!home.label) delete home.label
  if(!home.comment) delete home.comment
  if(!home.component) delete home.component
  if(!home.layout || Object.keys(home.layout).length === 0) {
    delete home.layout
  } else {
    clearLayout(home.layout)
    if(Object.keys(home.layout).length === 0) delete home.layout
  }
  if(!home.componentProps || Object.keys(home.componentProps).length === 0) {
    delete home.componentProps
  } else {
    clearComponentProps(home.componentProps)
    if(Object.keys(home.componentProps).length === 0) delete home.componentProps
  }

  if(!home.icon) delete home.icon
  if(!home.color) delete home.color
  if(!home.size) delete home.size
  if(!home.hoverColor) delete home.hoverColor
  
  if(home.affix === void 0) delete home.affix
  if(home.hidden === void 0) delete home.hidden
  if(home.breadcrumb === void 0) delete home.breadcrumb
  if(home.noTagsView === void 0) delete home.noTagsView

  if(!home.position || home.position.length === 0) delete home.position
  if(!home.mode) delete home.mode
}

function clearSeeds(seeds: Record<string, SeedConfiguration>) {
  for(const seedName in seeds) {
    const seed = seeds[seedName]
    clearHome(seed)

    if(!seed.tableName) delete seed.tableName
    if(!seed.tableSchema) delete seed.tableSchema
    if(!seed.type) delete seed.type
    if(!seed.nameColumn) delete seed.nameColumn

    if(!seed.columns || Object.keys(seed.columns).length === 0) {
      delete seed.columns
    } else {
      clearColumns(seed.columns)
      if(Object.keys(seed.columns).length === 0) delete seed.columns
    }

    if(!seed.actions || Object.keys(seed.actions).length === 0) {
      delete seed.actions
    } else {
      clearActions(seed.actions)
      if(Object.keys(seed.actions).length === 0) delete seed.actions
    }

    if(!seed.belongsTo || Object.keys(seed.belongsTo).length === 0) {
      delete seed.belongsTo
    } else {
      clearBelongsTo(seed.belongsTo)
      if(Object.keys(seed.belongsTo).length === 0) delete seed.belongsTo
    }

    if(!seed.hasOne || Object.keys(seed.hasOne).length === 0) {
      delete seed.hasOne
    } else {
      clearHasOne(seed.hasOne)
      if(Object.keys(seed.hasOne).length === 0) delete seed.hasOne
    }

    if(!seed.hasMany || Object.keys(seed.hasMany).length === 0) {
      delete seed.hasMany
    } else {
      clearHasMany(seed.hasMany)
      if(Object.keys(seed.hasMany).length === 0) delete seed.hasMany
    }

    if(!seed.habtm || Object.keys(seed.habtm).length === 0) {
      delete seed.habtm
    } else {
      clearHabtm(seed.habtm)
      if(Object.keys(seed.habtm).length === 0) delete seed.habtm
    }
    
    if(!seed.onSave) delete seed.onSave
    if(!seed.onUpdate) delete seed.onUpdate
    if(!seed.onSet) delete seed.onSet
    if(!seed.declares) delete seed.declares
    if(!seed.searches) delete seed.searches
    if(!seed.orders) delete seed.orders

    if(seed.useKeyword === void 0) delete seed.useKeyword
    if(seed.checkLogin === void 0) delete seed.checkLogin
    if(seed.checkAction === void 0) delete seed.checkAction
    if(seed.checkData === void 0) delete seed.checkData
    if(seed.checkField === void 0) delete seed.checkField

    if(!seed.stats || Object.keys(seed.stats).length === 0) {
      delete seed.stats
    } else {
      clearStats(seed.stats)
      if(Object.keys(seed.stats).length === 0) delete seed.stats
    }
  }
}

function clearActions(actions: Record<string, ActionConfiguration>) {
  for(const actionName in actions) {
    const action = actions[actionName]
    clearHome(action)

    if(!action.type) delete action.type
    if(!action.declare) delete action.declare
    if(!action.declareValue) delete action.declareValue
    if(!action.elements || Object.keys(action.elements).length === 0) {
      delete action.elements
    } else {
      clearElements(action.elements)
      if(Object.keys(action.elements).length === 0) delete action.elements
    }

    if(!action.seedName) delete action.seedName

    if(!action.declares) delete action.declares
    if(!action.searches) delete action.searches
    if(!action.orders) delete action.orders

    if(action.useKeyword === void 0) delete action.useKeyword
    if(action.checkLogin === void 0) delete action.checkLogin
    if(action.checkAction === void 0) delete action.checkAction
    if(action.checkData === void 0) delete action.checkData
    if(action.checkField === void 0) delete action.checkField

    if(!action.stats || Object.keys(action.stats).length === 0) {
      delete action.stats
    } else {
      clearStats(action.stats)
      if(Object.keys(action.stats).length === 0) delete action.stats
    }
  }
}

function clearMicros(micros: Record<string, MicroConfiguration>) {
  for(const microName in micros) {
    const micro = micros[microName]
    clearMicro(micro)
  }
}

function clearMicro(micro: MicroConfiguration) {
  if(!micro.label) delete micro.label
  if(!micro.comment) delete micro.comment
  if(!micro.component) delete micro.component
  if(!micro.layout || Object.keys(micro.layout).length === 0) {
    delete micro.layout
  } else {
    clearLayout(micro.layout)
  }
  if(!micro.componentProps || Object.keys(micro.componentProps).length === 0) {
    delete micro.componentProps
  } else {
    clearComponentProps(micro.componentProps)
  }

  if(!micro.icon) delete micro.icon
  if(!micro.color) delete micro.color
  if(!micro.size) delete micro.size
  if(!micro.hoverColor) delete micro.hoverColor

  if(!micro.homes || Object.keys(micro.homes).length === 0) {
    delete micro.homes
  } else {
    clearHomes(micro.homes)
  }

  if(!micro.seeds || Object.keys(micro.seeds).length === 0) {
    delete micro.seeds
  } else {
    clearSeeds(micro.seeds)
  }

  if(!micro.actions || Object.keys(micro.actions).length === 0) {
    delete micro.actions
  } else {
    clearActions(micro.actions)
  }

  if(!micro.libs || micro.libs.length === 0) delete micro.libs
}

function clearStats(stats: Record<string, StatConfiguration>) {
  for(const statName in stats) {
    const stat = stats[statName]
    if(!stat.label) delete stat.label
    if(!stat.comment) delete stat.comment
    if(!stat.type) delete stat.type
    if(!stat.declare) delete stat.declare
    if(!stat.searches || stat.searches.length === 0) delete stat.searches

    if(Object.keys(stat).length === 0) delete stats[statName]
  }
}

function clearColumns(columns: Record<string, ColumnConfiguration>) {
  for(const columnName in columns) {
    const column = columns[columnName]
    clearColumn(column)
  }
}

function clearElements(elements: Record<string, ElementConfiguration>) {
  for(const declare in elements) {
    const element = elements[declare]
    if(!element.element) delete element.element
    if(!element.elementProps || Object.keys(element.elementProps).length === 0) delete element.elementProps
  }
}

function clearColumn(column: ColumnConfiguration) {
  if(!column.type) delete column.type
  if(!column.label) delete column.label
  if(!column.comment) delete column.comment
  if(!column.length) delete column.length
  if(!column.defVal) delete column.defVal
  if(!column.precision) delete column.precision
  if(!column.scale) delete column.scale
  if(column.required === void 0) delete column.required
  if(column.unique === void 0) delete column.unique
  if(!column.min) delete column.min
  if(!column.max) delete column.max
  if(!column.rel) delete column.rel
  if(!column.options || Object.keys(column.options).length === 0) delete column.options
  if(!column.element) delete column.element  
  if(!column.elementProps || Object.keys(column.elementProps).length === 0) {
    delete column.elementProps
  } else {
    clearComponentProps(column.elementProps)
  }

  if(column.isLarge === void 0) delete column.isLarge
  if(!column.onInsertValue) delete column.onInsertValue
  if(!column.onUpdateValue) delete column.onUpdateValue
  if(!column.typeHandler) delete column.typeHandler
}

function clearBelongsTo(belongsTo: Record<string, BelongsToConfiguration>) {
  for(const cross in belongsTo) {
    const value = belongsTo[cross]
    if(!value.label) delete value.label
    if(!value.comment) delete value.comment
    if(!value.seedName) delete value.seedName
    if(!value.selfColumn) delete value.selfColumn
    if(!value.targetColumn) delete value.targetColumn
    if(!value.extraType) delete value.extraType
    if(!value.extra) delete value.extra

    if(Object.keys(value).length === 0) delete belongsTo[cross]
  }
}

function clearHasOne(hasOne: Record<string, HasOneConfiguration>) {
  clearBelongsTo(hasOne)
  for(const cross in hasOne) {
    const value = hasOne[cross]
    if(!value.cascade) delete value.cascade

    if(Object.keys(value).length === 0) delete hasOne[cross]
  }
}

function clearHasMany(hasMany: Record<string, HasManyConfiguration>) {
  clearHasOne(hasMany)
  for(const cross in hasMany) {
    const value = hasMany[cross]
    if(!value.limit) delete value.limit

    if(Object.keys(value).length === 0) delete hasMany[cross]
  }
}

function clearHabtm(habtm: Record<string, HabtmConfiguration>) {
  clearHasMany(habtm)
  for(const cross in habtm) {
    const value = habtm[cross]
    if(!value.throughSeedName) delete value.throughSeedName
    if(!value.throughSelfColumn) delete value.throughSelfColumn
    if(!value.throughTargetColumn) delete value.throughTargetColumn

    if(Object.keys(value).length === 0) delete habtm[cross]
  }
}